<template>
  <div id="container" class="map"></div>
</template>

<script>
export default {
  name: 'MapCluster',
  data() {
    return {
      map: null,
      cluster: null,
      points: [], // 替换为实际的点数据或动态获取
      district: {}, // 替换为实际的行政区数据
      amapKey: 'f8c954755588cd09132500151dc4d01c', // API key
    };
  },
  mounted() {
    this.loadStyles().then(() => {
      this.loadScripts().then(() => {
        this.initMap();
      });
    });
  },
  methods: {
    loadStyles() {
      return new Promise((resolve) => {
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = 'https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css';
        link.onload = resolve;
        document.head.appendChild(link);
      });
    },
    loadScripts() {
      const scripts = [
        'https://a.amap.com/jsapi_demos/static/data/community.js',
        'https://a.amap.com/jsapi_demos/static/data/district.js',
        `https://webapi.amap.com/maps?v=2.0&key=${this.amapKey}&plugin=AMap.IndexCluster`
      ];

      return Promise.all(scripts.map(src => {
        return new Promise((resolve, reject) => {
          const script = document.createElement('script');
          script.src = src;
          script.onload = resolve;
          script.onerror = reject;
          document.head.appendChild(script);
        });
      }));
    },
    initMap() {
      this.map = new AMap.Map("container", {
        zoom: 9,
        animateEnable: true,
        mapStyle: "amap://styles/grey",
      });
      
      // 初始化聚合
      this.cluster = new AMap.IndexCluster(this.map, this.points, {
        renderClusterMarker: this._renderClusterMarker,
        clusterIndexSet: this.clusterIndexSet(),
      });
    },
    clusterIndexSet() {
      return {
        city: {
          minZoom: 2,
          maxZoom: 10,
        },
        district: {
          minZoom: 10,
          maxZoom: 12,
        },
        area: {
          minZoom: 12,
          maxZoom: 15,
        },
        community: {
          minZoom: 15,
          maxZoom: 22,
        },
      };
    },
    getStyle(context) {
      const clusterData = context.clusterData;
      const index = context.index;
      const count = context.count;
      const color = [
        '8,60,156',
        '66,130,198',
        '107,174,214',
        '78,200,211',
      ];
      const indexs = ['city', 'district', 'area', 'community'];
      const i = indexs.indexOf(index['mainKey']);
      let text = clusterData[0][index['mainKey']];
      let size = Math.round(30 + Math.pow(count / this.points.length, 1 / 5) * 70);
      if (i <= 2) {
        const extra = `<span class="showCount">${context.count}套</span>`;
        text = `<span class="showName">${text}</span>${extra}`;
      } else {
        size = 12 * text.length + 20;
      }
      return {
        bgColor: `rgba(${color[i]},.8)`,
        borderColor: `rgba(${color[i]},1)`,
        text: text,
        size: size,
        index: i,
        color: '#ffffff',
        textAlign: 'center',
        boxShadow: '0px 0px 5px rgba(0,0,0,0.8)',
      };
    },
    getPosition(context) {
      const key = context.index.mainKey;
      const dataItem = context.clusterData && context.clusterData[0];
      const districtName = dataItem[key];
      if (!this.district[districtName]) {
        return null;
      }
      const center = this.district[districtName].center.split(',');
      return new AMap.LngLat(center[0], center[1]);
    },
    _renderClusterMarker(context) {
      const styleObj = this.getStyle(context);
      const div = document.createElement('div');
      div.className = 'amap-cluster';
      div.style.backgroundColor = styleObj.bgColor;
      div.style.width = `${styleObj.size}px`;
      if (styleObj.index <= 2) {
        div.style.height = `${styleObj.size}px`;
        context.marker.on('click', (e) => {
          const curZoom = this.map.getZoom();
          if (curZoom < 20) {
            this.map.setZoomAndCenter(curZoom + 1, e.lnglat);
          }
        });
      }
      div.style.border = `solid 1px ${styleObj.borderColor}`;
      div.style.borderRadius = `${styleObj.size}px`;
      div.innerHTML = styleObj.text;
      div.style.color = styleObj.color;
      div.style.textAlign = styleObj.textAlign;
      div.style.boxShadow = styleObj.boxShadow;
      context.marker.setContent(div);
      
      const position = this.getPosition(context);
      if (position) {
        context.marker.setPosition(position);
      }
      context.marker.setAnchor('center');
    },
  },
};
</script>

<style scoped>
html, body, #container {
  height: 100%;
  width: 100%;
}
.amap-cluster {
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
  font-size: 12px;
}
.showName {
  font-size: 14px;
}
.showCount, .showName {
  display: block;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
  width: 80%;
}
</style>
